package com.cougil.uoc.seghismed.model;

import org.apache.log4j.Logger;

import iaik.asn1.ObjectID;
import iaik.asn1.structures.Name;
import iaik.x509.X509Certificate;

import java.security.cert.CertificateException;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

import com.cougil.uoc.seghismed.model.enums.UnitatOrganitzativa;

/**
 * Entitat de negoci que representa pròpiament a un Usuari 
 * @author Ignacio Cougil Jares
 *
 */
@Entity
@Table(
        name="USUARI",
        uniqueConstraints= 
            @UniqueConstraint(columnNames={"DNI"})
)
/* Cada entitat emmagatzemarà les seves dades particulars en una taula apart, però les dades comunes
 * romandran a la taula que guardarà la informació d'aquesta entitat pare
 */
@Inheritance(strategy=InheritanceType.JOINED)

public class Usuari {
	
	private static final Logger logger = Logger.getLogger(Usuari.class);

	@Id
	@GeneratedValue
	private Integer id;
	private String nom;
	private String primerCognom;
	private String segonCognom;
	private String dni;
	@Enumerated(EnumType.STRING)
	private UnitatOrganitzativa unitatOrganitzativa;
	private Date dataAlta;
	private Date dataModificacio;
	@Lob
	@Column(name = "CERTIFICAT")
	private byte[] certificat;
	
	/**
	 * @return Retorna el valor de la propietat id
	 */
	public Integer getId() {
		return id;
	}



	/**
	 * @param id Estableix el valor de la propietat id
	 */
	public void setId(Integer id) {
		this.id = id;
	}



	/**
	 * @return Retorna el valor de la propietat nom
	 */
	public String getNom() {
		return nom;
	}



	/**
	 * @param nom Estableix el valor de la propietat nom
	 */
	public void setNom(String nom) {
		this.nom = nom;
	}



	/**
	 * @return Retorna el valor de la propietat primerCognom
	 */
	public String getPrimerCognom() {
		return primerCognom;
	}



	/**
	 * @param primerCognom Estableix el valor de la propietat primerCognom
	 */
	public void setPrimerCognom(String primerCognom) {
		this.primerCognom = primerCognom;
	}



	/**
	 * @return Retorna el valor de la propietat segonCognom
	 */
	public String getSegonCognom() {
		return segonCognom;
	}



	/**
	 * @param segonCognom Estableix el valor de la propietat segonCognom
	 */
	public void setSegonCognom(String segonCognom) {
		this.segonCognom = segonCognom;
	}



	/**
	 * @return Retorna el valor de la propietat dni
	 */
	public String getDni() {
		return dni;
	}



	/**
	 * @param dni Estableix el valor de la propietat dni
	 */
	public void setDni(String dni) {
		this.dni = dni;
	}



	/**
	 * @return Retorna el valor de la propietat unitatOrganitzativa
	 */
	public UnitatOrganitzativa getUnitatOrganitzativa() {
		return unitatOrganitzativa;
	}



	/**
	 * @param unitatOrganitzativa Estableix el valor de la propietat unitatOrganitzativa
	 */
	public void setUnitatOrganitzativa(UnitatOrganitzativa unitatOrganitzativa) {
		this.unitatOrganitzativa = unitatOrganitzativa;
	}
	
	

	/**
	 * @return Retorna el valor de la propietat dataAlta
	 */
	public Date getDataAlta() {
		return dataAlta;
	}



	/**
	 * @param Estableix dataAlta com a valor de la propietat dataAlta
	 */
	public void setDataAlta(Date dataAlta) {
		this.dataAlta = dataAlta;
	}



	/**
	 * @return Retorna el valor de la propietat dataModificacio
	 */
	public Date getDataModificacio() {
		return dataModificacio;
	}



	/**
	 * @param Estableix dataModificacio com a valor de la propietat dataModificacio
	 */
	public void setDataModificacio(Date dataModificacio) {
		this.dataModificacio = dataModificacio;
	}


	/**
	 * @return Retorna el valor de la propietat certificat
	 */
	public byte[] getCertificat() {
		return certificat;
	}



	/**
	 * @param bytesCertificat Estableix el valor de la propietat certificat
	 */
	public void setCertificat(byte[] certificat) {
		this.certificat = certificat;
	}
	

	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(final Object other) {
		if (!(other instanceof Usuari))
			return false;
		Usuari castOther = (Usuari) other;
		return new EqualsBuilder().append(dni, castOther.dni).isEquals();
	}



	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return new HashCodeBuilder().append(dni).toHashCode();
	}



	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
			.append("id", id)
			.append("nom", nom)
			.append("primerCognom", primerCognom)
			.append("segonCognom", segonCognom)
			.append("dni", dni)
			.append("unitatOrganitzativa", unitatOrganitzativa)
			.append("dataAlta", dataAlta)
			.append("dataModificacio", dataModificacio)
			.append("certificat", toStringCertificat())
			.toString();
	}

	private String toStringCertificat() {
		String str = null;
		if (this.certificat != null) {
			try {
				X509Certificate cert = new X509Certificate(this.certificat);
				String serial = cert.getSerialNumber()+"";
				Name name = (Name) cert.getSubjectDN();
				String nom = name.getRDN(ObjectID.commonName);
				String email = name.getRDN(ObjectID.emailAddress);
				str = nom+" "+email+" ["+serial+"]";
			} catch (CertificateException e) {
				logger.error("Format del certificat erroni. Motiu: "+e.fillInStackTrace());
			}
			
		}
		return str;
	}




}
